#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using SpriteSheetRuntime;
using System.Collections.Generic;
#endregion

namespace TvGame
{
     public enum Days
        {
            Monday,
            Tuesday,
            Wednesday,
            Thursday,
            Friday,
            Saturday,
            Sunday,
        };
     public enum Time
     {
         Morning,
         Lunch,
         Evening,
         Night,
     };

     public enum AiState
     {
         Chasing,
         Caught,
         Wander
     };
     
    /// <summary>
    /// This screen implements the actual game logic. It is just a
    /// placeholder to get the idea across: you'll probably want to
    /// put some more interesting gameplay in here!
    /// </summary>
    class GameplayScreen : GameScreen
    {
        #region Fields
       
        public string[] MorningShows =
     {
         "Breakfast",
         "Cartoons",
         "News"
     };
     public string[] LunchShows =
     {
         "TalkShows",
         "Documentaries",
         "News"
     };
     public string[] EveningShows =
     {
         "News",
         "Documentaries"
     };
     public string[] NightShows =
     {
         "News",
         "Documentaries"
     };


        ContentManager content;
        SpriteFont gameFont;
        SpriteFont guiFont;

        Random random;

        GameObjects player;
        Texture2D playerSprite;
        Rectangle playerRect;

        GameObjects[] enemies;     
        Texture2D ehealthBar;
        int maxEnemies = 10;
        AiState enemyState = AiState.Wander;
        const float MaxEnemySpeed = 2.5f;
        const float enemyTurnSpeed = 0.10f;
        const float enemyDistance = 150.0f;
        const float enemyHysteresis = 15.0f;
        const float enemyChaseDistance = 150.0f;
        Vector2 enemyWanderDirection;
        const float enemyCaughtDistance = 60.0f;
        double attackTimer;

        GameObjects miniBoss;
        bool miniBossSpawn = false;

        GameObjects turret;        
        bool newTurret = false;
        int turretRange = 800;
        float bulletTimer;
        bool attacking = false;

        Texture2D background;

        List<BloodDisplay> blood;
        Texture2D bloodTexture;

        GameObjects[] bullets;
        int maxBullets = 50;
        int ammo;

        Texture2D healthBar;        

        GameObjects zap;
        Texture2D zapSprite;
        SpriteSheet zapSheet;

        KeyboardState prevKeyboard = Keyboard.GetState();

        Camera2d Camera;
        int gameWidth = 1000;
        int gameHeight = 1500;
        Rectangle gameRect;

        int kills = 0;
        int killsGained = 0;
        int killsInPeriod = 10;
        int miniBossKills = 0;
        public static int score;

        float dt;
        float countdown = 5;

        float pauseAlpha;

        int dayInt;
        int timeInt;
        String dayString;
        String timeString;
        bool periodOver = false;

        public static String nextShow;
        int nextShowInt;

        public static bool showInterval = false;

        Texture2D remote;

        #endregion

        #region Initialization


        /// <summary>
        /// Constructor.
        /// </summary>
        public GameplayScreen()
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);

            random = new Random();

            periodOver = false;

            dayString = Days.Monday.ToString();
            dayInt = 1;

            timeString = Time.Morning.ToString();
            timeInt = 1;
        }


        /// <summary>
        /// Load graphics content for the game.
        /// </summary>
        public override void LoadContent()
        {
            if (content == null)
                content = new ContentManager(ScreenManager.Game.Services, "Content");

            gameRect = new Rectangle(0, 0, gameWidth, gameHeight);

            gameFont = content.Load<SpriteFont>("gamefont");
            guiFont = content.Load<SpriteFont>("guifont");

            healthBar = content.Load<Texture2D>("Sprites//healthbar2");
            ehealthBar = content.Load<Texture2D>("Sprites//health bar");

            blood = new List<BloodDisplay>();
            bloodTexture = content.Load<Texture2D>("Sprites//blood");

            remote = content.Load<Texture2D>("Sprites//Remote");

            playerSprite = content.Load<Texture2D>("Sprites//Player//joe");
            player = new GameObjects(playerSprite);
            player.sprite = playerSprite;
            player.position = new Vector2(
                    (float)random.Next(gameRect.Width), (float)random.Next(gameRect.Height));            

            zapSheet = content.Load<SpriteSheet>("Sprites//Player//spritesheet");
            zapSprite = content.Load<Texture2D>("Sprites//Player//zapBlank");
            zap = new GameObjects(zapSprite);

            enemies = new GameObjects[maxEnemies];
                for (int i = 0;
                    i < maxEnemies;
                    i++)
                {
                    enemies[i] = new GameObjects(content.Load<Texture2D>
                        ("Sprites//enemy1"));                    
                }
                foreach (GameObjects enemy in enemies)
                {
                    enemy.alive = true;
                    enemy.position = new Vector2(
                        (float)random.Next(gameRect.Width),
                        (float)random.Next(gameRect.Height));
                }

            miniBoss = new GameObjects(content.Load<Texture2D>("Sprites\\Player\\player"));
            miniBoss.position = new Vector2(
                        (float)random.Next(gameRect.Width),
                        (float)random.Next(gameRect.Height));
            miniBoss.alive = false;
            miniBoss.health = 500;

            turret = new GameObjects(content.Load<Texture2D>("Sprites\\Player\\player"));


           bullets = new GameObjects[maxBullets];
                for (int i = 0;
                    i < maxBullets;
                    i++)
                {
                    bullets[i] = new GameObjects(content.Load<Texture2D>
                        ("Sprites//bullet"));                    
                }                
            //vpRect = new Rectangle(0, 0, ScreenManager.GraphicsDevice.Viewport.Width, ScreenManager.GraphicsDevice.Viewport.Height);
            background = content.Load<Texture2D>("Sprites//Scenery//wood");

            Camera = new Camera2d(ScreenManager.GraphicsDevice.Viewport, gameWidth, gameHeight, 1);

            // once the load has finished, we use ResetElapsedTime to tell the game's
            // timing mechanism that we have just finished a very long frame, and that
            // it should not try to catch up.
            ScreenManager.Game.ResetElapsedTime();
        }

        public void LoadWave()
        {            
            maxEnemies += 2;
            killsInPeriod += 2;

            enemies = new GameObjects[maxEnemies];
            for (int i = 0;
                i < maxEnemies;
                i++)
            {
                enemies[i] = new GameObjects(content.Load<Texture2D>
                    ("Sprites//enemy1"));

                enemies[i].alive = true;
            }

            foreach (GameObjects enemy in enemies)
            {
                enemy.position = new Vector2(
                    (float)random.Next(gameRect.Width), (float)random.Next(gameRect.Height));
            }
        }
             
        /// <summary>
        /// Unload graphics content used by the game.
        /// </summary>
        public override void UnloadContent()
        {
            content.Unload();
        }


        #endregion

        #region Update and Draw


        /// <summary>
        /// Updates the state of the game. This method checks the GameScreen.IsActive
        /// property, so the game will stop updating when the pause menu is active,
        /// or if you tab away to a different application.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, false);

            // Gradually fade in or out depending on whether we are covered by the pause screen.
            if (coveredByOtherScreen)
                pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1);
            else
                pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0);

            if (IsActive)
            {
                dt = (float)gameTime.ElapsedGameTime.TotalSeconds;

                foreach (GameObjects enemy in enemies)
                {
                    enemy.position = ClampToViewport(enemy.position);
                    
                    if (enemy.health <= 0 && enemy.alive == true)
                    {
                        enemy.alive = false;
                        score += 10;
                        kills += 1;
                        killsGained += 1;
                        break;
                    }
                }

                //if (health == 0)
                //{
                //    lives -= 1;
                 //   score -= 200;
                 //   health = 100;
                //}
                if (player.health <= 0)
                {
                    ScreenManager.AddScreen(new GameOverScreen(), PlayerIndex.One);
                }

                UpdateEnemies(gameTime);
                UpdateTurrets();
                UpdateBullets();
                UpdateZap();
                UpdateMiniBoss(gameTime);

                miniBossKills = killsInPeriod += 1;

                zap.position = player.position;
                zap.rotation = player.rotation;

                if (newTurret == true)
                {
                    turret.position = player.position;
                    turret.alive = true;
                    newTurret = false;
                }
                bulletTimer += 0.05f;

                player.position = ClampToViewport(player.position);
                player.health = (int)MathHelper.Clamp(player.health, 0, 100);
                playerRect = new Rectangle((int)player.position.X, (int)player.position.Y, 
                    player.sprite.Width, player.sprite.Height);

                if (killsGained == killsInPeriod)
                {                    
                    countdown -= (float)gameTime.ElapsedGameTime.TotalSeconds;                    
                    if (countdown <= 0)
                    {                                          
                        periodOver = true;
                        countdown = 5;                        
                        LoadWave();                       
                        killsGained = 0;
                        showInterval = true;
                    }
                }

                if (showInterval == true)
                {
                    if (timeInt == 1)
                    {
                        nextShowInt = random.Next(1, 3);
                        nextShow = MorningShows[nextShowInt].ToString();                        
                    }
                    if (timeInt == 2)
                    {
                        nextShowInt = random.Next(1, 2);
                        nextShow = LunchShows[nextShowInt].ToString();
                    }
                    if (timeInt == 3)
                    {
                        nextShowInt = random.Next(1, 2);
                        nextShow = EveningShows[nextShowInt].ToString();
                    }
                    if (timeInt == 4)
                    {
                        nextShowInt = random.Next(1, 2);
                        nextShow = NightShows[nextShowInt].ToString();
                    }
                    ScreenManager.AddScreen(new IntervalScreen(), ControllingPlayer);
                    showInterval = false;
                }

                if (periodOver == true)
                {
                    foreach (BloodDisplay bloods in blood)
                    {
                        bloods.IsVisible = false;
                    }

                    if (timeInt == 4)
                    {
                        dayInt++;
                        timeInt = 1;
                        periodOver = false;
                    }
                    else
                    {
                        timeInt++;
                        periodOver = false;
                    }
                }

                if (dayInt == 1)
                    dayString = Days.Monday.ToString();
                if (dayInt == 2)
                    dayString = Days.Tuesday.ToString();
                if (dayInt == 3)
                    dayString = Days.Wednesday.ToString();
                if (dayInt == 4)
                    dayString = Days.Thursday.ToString();
                if (dayInt == 5)
                    dayString = Days.Friday.ToString();
                if (dayInt == 6)
                    dayString = Days.Saturday.ToString();
                if (dayInt == 7)
                    dayString = Days.Sunday.ToString();
                if (dayInt > 7)
                    dayInt = 1;


                if (timeInt == 1)
                    timeString = Time.Morning.ToString();
                if (timeInt == 2)
                    timeString = Time.Lunch.ToString();
                if (timeInt == 3)
                    timeString = Time.Evening.ToString();
                if (timeInt == 4)
                    timeString = Time.Night.ToString();
                if (timeInt > 4)
                    timeInt = 1;

                //miniBoss Spawing
                if (timeInt == 4)
                {
                    miniBossSpawn = true;
                    killsInPeriod = miniBossKills;
                }
                else
                    miniBossSpawn = false;

            }
        }

        public bool IsInRange(Vector2 position)
        {
            if (Vector2.Distance(turret.center, position) <= turretRange)
                return true;
            return false;
        }
        public void UpdateTurrets()
        {
            float smallestRange = turretRange;
            GameObjects closest = null;
            if (turret.alive)
            {
                foreach (GameObjects enemy in enemies)
                {
                    if (enemy.alive == true)
                    {
                        float distance = Vector2.Distance(turret.position, enemy.position);
                        if (distance < smallestRange)
                        {
                            smallestRange = distance;
                            closest = enemy;
                            //attacking = true;
                            if (IsInRange(closest.center) && closest != null)
                            {
                                attacking = true;
                            }
                            if (attacking && bulletTimer >= 5)
                            {
                                if (closest == null || !IsInRange(closest.center))
                                    attacking = false;
                                else
                                {
                                    TurretFire();
                                    bulletTimer = 0;
                                }
                            }
                            turret.rotation = TurnToFace(turret.position, closest.position, turret.rotation, 0.1f);
                        }
                    }

                }

            }
        }
        
        
        public void UpdateEnemies(GameTime gameTime)
        {
            foreach (GameObjects enemy in enemies)
            {
                if (enemy.alive)
                {
                    if (!gameRect.Contains(new Point(
                       (int)enemy.position.X,
                       (int)enemy.position.Y)))
                    {
                        enemy.alive = false;
                        //killsGained += 1;
                    }
                    else
                    {
                        enemy.alive = true;

                        Rectangle enemyRect = new Rectangle((int)enemy.position.X, 
                            (int)enemy.position.Y, enemy.sprite.Width, enemy.sprite.Height);

                        if (playerRect.Intersects(enemyRect))
                        {
                            attackTimer -= gameTime.ElapsedGameTime.TotalSeconds;

                            if (attackTimer <= 0)
                            {
                                player.health -= 1.5f;
                                attackTimer = 0.5;
                            }       
                        }

                        float enemyChaseThreshold = enemyChaseDistance;
                        float enemyCaughtThreshold = enemyCaughtDistance;

                        if (enemyState == AiState.Wander)
                        {
                            enemyChaseThreshold -= enemyHysteresis / 2;
                        }
                        else if (enemyState == AiState.Chasing)
                        {
                            enemyChaseThreshold += enemyHysteresis / 2;
                            enemyCaughtThreshold -= enemyHysteresis / 2;
                        }
                        else if (enemyState == AiState.Caught)
                        {
                            enemyCaughtThreshold += enemyHysteresis / 2;
                        }
                        float distanceFromCat = Vector2.Distance(enemy.position, player.position);
                        if (distanceFromCat > enemyChaseThreshold)
                        {
                            enemyState = AiState.Wander;
                        }
                        else if (distanceFromCat > enemyCaughtThreshold)
                        {
                            enemyState = AiState.Chasing;
                        }
                        else
                        {
                            enemyState = AiState.Caught;
                        }

                        if (enemyState == AiState.Chasing)
                        {
                            enemy.rotation = TurnToFace(enemy.position, player.position, enemy.rotation,
                                enemyTurnSpeed);
                            enemy.speed = MaxEnemySpeed;
                        }
                        if (enemyState == AiState.Wander)
                        {
                            Wander(enemy.position, ref enemyWanderDirection, ref enemy.rotation,
                                enemyTurnSpeed);
                            enemy.speed = .25f * MaxEnemySpeed;
                        }
                        if (enemyState == AiState.Caught)
                        {
                            enemy.speed = MaxEnemySpeed;
                        }

                        Vector2 heading = new Vector2(
                             (float)Math.Cos(enemy.rotation), (float)Math.Sin(enemy.rotation));
                        enemy.position += heading * enemy.speed;
                    }
                }
                else
                {
                    bool isNewBloodRequired = true;
                    foreach (BloodDisplay bloodS in blood)
                    {
                        if (!bloodS.IsVisible)
                        {
                            isNewBloodRequired = false;
                            bloodS.Reset(enemy.position, bloodTexture, 500.0f);
                            break;
                        }
                    }

                    if (isNewBloodRequired)
                    {
                        blood.Add(new BloodDisplay(content, enemy.position, bloodTexture, 500.0f));
                    } 

                }
            }
        }

        public void UpdateMiniBoss(GameTime gameTime)
        {
            if (miniBossSpawn == true)
                {
                    if (!gameRect.Contains(new Point(
                       (int)miniBoss.position.X,
                       (int)miniBoss.position.Y)))
                    {
                        miniBoss.alive = false;
                        //killsGained += 1;
                    }
                    else
                    {
                        miniBoss.alive = true;

                        Rectangle miniBossRect = new Rectangle((int)miniBoss.position.X,
                            (int)miniBoss.position.Y, miniBoss.sprite.Width, miniBoss.sprite.Height);

                        if (playerRect.Intersects(miniBossRect))
                        {
                            attackTimer -= gameTime.ElapsedGameTime.TotalSeconds;

                            if (attackTimer <= 0)
                            {
                                player.health -= 1.5f;
                                attackTimer = 0.5;
                            }
                        }

                        float miniBossChaseThreshold = enemyChaseDistance;
                        float miniBossCaughtThreshold = enemyCaughtDistance;

                        if (enemyState == AiState.Wander)
                        {
                            miniBossChaseThreshold -= enemyHysteresis / 2;
                        }
                        else if (enemyState == AiState.Chasing)
                        {
                            miniBossChaseThreshold += enemyHysteresis / 2;
                            miniBossCaughtThreshold -= enemyHysteresis / 2;
                        }
                        else if (enemyState == AiState.Caught)
                        {
                            miniBossCaughtThreshold += enemyHysteresis / 2;
                        }
                        float distanceFromCat = Vector2.Distance(miniBoss.position, player.position);
                        if (distanceFromCat > miniBossChaseThreshold)
                        {
                            enemyState = AiState.Wander;
                        }
                        else if (distanceFromCat > miniBossCaughtThreshold)
                        {
                            enemyState = AiState.Chasing;
                        }
                        else
                        {
                            enemyState = AiState.Caught;
                        }

                        if (enemyState == AiState.Chasing)
                        {
                            miniBoss.rotation = TurnToFace(miniBoss.position, player.position, miniBoss.rotation,
                                enemyTurnSpeed);
                            miniBoss.speed = MaxEnemySpeed;
                        }
                        if (enemyState == AiState.Wander)
                        {
                            Wander(miniBoss.position, ref enemyWanderDirection, ref miniBoss.rotation,
                                enemyTurnSpeed);
                            miniBoss.speed = .25f * MaxEnemySpeed;
                        }
                        if (enemyState == AiState.Caught)
                        {
                            miniBoss.speed = MaxEnemySpeed;
                        }

                        Vector2 heading = new Vector2(
                             (float)Math.Cos(miniBoss.rotation), (float)Math.Sin(miniBoss.rotation));
                        miniBoss.position += heading * miniBoss.speed;
                    }
                }
                else
                {
                    bool isNewBloodRequired = true;
                    foreach (BloodDisplay bloodS in blood)
                    {
                        if (!bloodS.IsVisible)
                        {
                            isNewBloodRequired = false;
                            bloodS.Reset(miniBoss.position, bloodTexture, 500.0f);
                            break;
                        }
                    }

                    if (isNewBloodRequired)
                    {
                        blood.Add(new BloodDisplay(content, miniBoss.position, bloodTexture, 500.0f));
                    }

                }
            }

        public void UpdateZap()
        {
            if (zap.alive)
            {                
                zap.position = player.position;
                zap.rotation = player.rotation;

                Rectangle zapRect = new Rectangle(
                        (int)zap.position.X,
                        (int)zap.position.Y,
                        zap.sprite.Width,
                        zap.sprite.Height);

                foreach (GameObjects enemy in enemies)
                {
                    Rectangle enemyRect = new Rectangle(
                        (int)enemy.position.X,
                        (int)enemy.position.Y,
                        enemy.sprite.Width,
                        enemy.sprite.Height);

                    // Check collision with enemies
                    if (zapRect.Intersects(enemyRect) && enemy.alive)
                    {
                        enemy.health -= 0.7f;
                        //break;
                    }
                }                         
            }
        }

        public void FireBullet()
        {
            ammo -= 1;            
            foreach (GameObjects bullet in bullets)
            {
                if (!bullet.alive)
                {
                    bullet.alive = true;
                    bullet.position = player.position - bullet.center;
                    bullet.velocity = new Vector2(
                        (float)
                        Math.Cos(player.rotation),
                        (float)Math.Sin(player.rotation))
                        * 10.0f;
                    return;
                }
            }
        }

        public void TurretFire()
        {
            //ammo -= 1;
            foreach (GameObjects bullet in bullets)
            {
                if (!bullet.alive)
                {
                    bullet.alive = true;
                    bullet.position = turret.position - bullet.center;
                    bullet.velocity = new Vector2(
                        (float)
                        Math.Cos(turret.rotation),
                        (float)Math.Sin(turret.rotation))
                        * 10.0f;
                    return;
                }
            }
        }
        public void UpdateBullets()
        {
            foreach (GameObjects bullet in bullets)
            {
                if (bullet.alive)
                {
                    bullet.position += bullet.velocity * 4;
                    if (!gameRect.Contains(new Point(
                        (int)bullet.position.X,
                        (int)bullet.position.Y)))
                    {
                        bullet.alive = false;
                        continue;

                    }
                    Rectangle bulletRect = new Rectangle(
                        (int)bullet.position.X,
                        (int)bullet.position.Y,
                        bullet.sprite.Width,
                        bullet.sprite.Height);

                    foreach (GameObjects enemy in enemies)
                    {
                        Rectangle enemyRect = new Rectangle(
                            (int)enemy.position.X,
                            (int)enemy.position.Y,
                            enemy.sprite.Width,
                            enemy.sprite.Height);

                        // Check collision with person
                       if(enemyRect.Intersects(bulletRect)
                            && enemy.alive)
                        {
                            bullet.alive = false;
                            enemy.alive = false;
                            //hit.Play();
                            score += 10;
                            kills += 1;
                            killsGained += 1;
                        }
                    }
                }
            }
        }
            
        private Vector2 ClampToViewport(Vector2 vector)
        {
            vector.X = MathHelper.Clamp(vector.X, gameRect.X, gameRect.X + gameRect.Width);
            vector.Y = MathHelper.Clamp(vector.Y, gameRect.Y, gameRect.Y + gameRect.Height);
            return vector;
        }
        /// <summary>
        /// Lets the game respond to player input. Unlike the Update method,
        /// this will only be called when the gameplay screen is active.
        /// </summary>
        public override void HandleInput(InputState input)
        {
            if (input == null)
                throw new ArgumentNullException("input");

            // Look up inputs for the active player profile.
            int playerIndex = (int)ControllingPlayer.Value;

            KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex];
            GamePadState gamePadState = input.CurrentGamePadStates[playerIndex];

            // The game pauses either if the user presses the pause button, or if
            // they unplug the active gamepad. This requires us to keep track of
            // whether a gamepad was ever plugged in, because we don't want to pause
            // on PC if they are playing with a keyboard and have no gamepad at all!
            bool gamePadDisconnected = !gamePadState.IsConnected &&
                                       input.GamePadWasConnected[playerIndex];

            if (input.IsPauseGame(ControllingPlayer) || gamePadDisconnected)
            {
                ScreenManager.AddScreen(new PauseMenuScreen(), ControllingPlayer);
            }
            else
            {                
                // Otherwise move the player position.
                Vector2 movement = Vector2.Zero;

                if (keyboardState.IsKeyDown(Keys.A))
                    player.rotation -= 5f * dt;

                if (keyboardState.IsKeyDown(Keys.D))
                    player.rotation += 5f * dt;

                if (keyboardState.IsKeyDown(Keys.W))
                {
                    Vector2 tempPos = player.position;
                    tempPos.X += 190 * (float)Math.Cos(player.rotation) * dt;
                    tempPos.Y += 190 * (float)Math.Sin(player.rotation) * dt;
                    player.position = tempPos;
                }

                if (keyboardState.IsKeyDown(Keys.S))
                {
                    Vector2 tempPos = player.position;
                    tempPos.X -= 70 * (float)Math.Cos(player.rotation) * dt;
                    tempPos.Y -= 70 * (float)Math.Sin(player.rotation) * dt;
                    player.position = tempPos;
                }

                if (keyboardState.IsKeyDown(Keys.NumPad0) && prevKeyboard.IsKeyUp(Keys.NumPad0))
                {                    
                    zap.alive = true;
                }
                if (keyboardState.IsKeyUp(Keys.NumPad0))
                {
                    zap.alive = false;
                }

                if (keyboardState.IsKeyDown(Keys.NumPad1))
                {
                    newTurret = true;
                }
                if (keyboardState.IsKeyUp(Keys.NumPad1))
                {
                    newTurret = false;
                }
                //Health Debug
               // if (keyboardState.IsKeyDown(Keys.Up))
               // {
               //     player.health += 1;
               // }
               // if (keyboardState.IsKeyDown(Keys.Down))
               // {
               //     player.health -= 1;
               // }

                Camera.Pos = player.position;
                prevKeyboard = keyboardState;
            }
        }


        /// <summary>
        /// Draws the gameplay screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            // This game has a blue background. Why? Because!
            ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
                                               Color.CornflowerBlue, 0, 0);

            // Our player and enemy are both actually just text strings.
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;

            Vector2 shadowOffset = Vector2.One;

            float time = (float)gameTime.TotalGameTime.TotalSeconds;

            spriteBatch.Begin(SpriteSortMode.BackToFront,
                    null, null, null, null, null,
                    Camera.GetTransformation());

            spriteBatch.Draw(background, new Rectangle(0, 0, gameWidth, gameHeight), null, Color.White, 0f, Vector2.Zero, SpriteEffects.None, 1);

            foreach (BloodDisplay bloods in blood)
            {
                bloods.Draw(spriteBatch);
            }

            spriteBatch.Draw(player.sprite, player.position + shadowOffset, null, Color.Black,
                     player.rotation, player.center, 1f, SpriteEffects.None, 0.9f);
            spriteBatch.Draw(player.sprite, player.position, null, Color.White,
                    player.rotation, player.center, 1f, SpriteEffects.None, 0);

            foreach (GameObjects enemy in enemies)
            {
                if (enemy.alive == true)
                {
                    spriteBatch.Draw(enemy.sprite, enemy.position + shadowOffset, null, Color.Black,
                        enemy.rotation, enemy.center, 1.0f, SpriteEffects.None, 0.5f);
                    spriteBatch.Draw(enemy.sprite, enemy.position, null, Color.White,
                            enemy.rotation, enemy.center, 1.0f, SpriteEffects.None, 0);

                    // Draw the health bar normally.
                    Rectangle healthRectangle = new Rectangle((int)enemy.position.X,
                                                             (int)enemy.position.Y,
                                                             ehealthBar.Width,
                                                             ehealthBar.Height);

                    spriteBatch.Draw(ehealthBar, healthRectangle, null, Color.Gray, 0f, enemy.center, SpriteEffects.None, 0.89f);

                    float healthPercentage = enemy.health / 100;
                    float visibleWidth = (float)ehealthBar.Width * healthPercentage;

                    healthRectangle = new Rectangle((int)enemy.position.X,
                                                   (int)enemy.position.Y,
                                                   (int)(visibleWidth),
                                                   ehealthBar.Height);

                    spriteBatch.Draw(ehealthBar, healthRectangle, null, Color.Gold, 0f, enemy.center, SpriteEffects.None, 0.8f);
                }
            }

            if (miniBoss.alive)
            {
                spriteBatch.Draw(miniBoss.sprite, miniBoss.position + shadowOffset, null, Color.Black,
                        miniBoss.rotation, miniBoss.center, 1.0f, SpriteEffects.None, 0.5f);
                spriteBatch.Draw(miniBoss.sprite, miniBoss.position, null, Color.White,
                        miniBoss.rotation, miniBoss.center, 1.0f, SpriteEffects.None, 0);

                // Draw the health bar normally.
                Rectangle healthRectangle = new Rectangle((int)miniBoss.position.X,
                                                         (int)miniBoss.position.Y,
                                                         ehealthBar.Width,
                                                         ehealthBar.Height);

                spriteBatch.Draw(ehealthBar, healthRectangle, null, Color.Gray, 0f, miniBoss.center, SpriteEffects.None, 0.89f);

                float healthPercentage = miniBoss.health / 100;
                float visibleWidth = (float)ehealthBar.Width * healthPercentage;

                healthRectangle = new Rectangle((int)miniBoss.position.X,
                                               (int)miniBoss.position.Y,
                                               (int)(visibleWidth),
                                               ehealthBar.Height);

                spriteBatch.Draw(ehealthBar, healthRectangle, null, Color.Gold, 0f, miniBoss.center, SpriteEffects.None, 0.8f);
            }
            if (zap.alive)
            {
                const int animationFramesPerSecond = 10;
                const int animationFrameCount = 5;

                // Look up the index of the first glow sprite.
                int glowIndex = zapSheet.GetIndex("zap1");

                // Modify the index to select the current frame of the animation.
                glowIndex += (int)(time * animationFramesPerSecond) % animationFrameCount;

                // Draw the current glow sprite.
                spriteBatch.Draw(zapSheet.Texture, zap.position,
                                 zapSheet.SourceRectangle(glowIndex), Color.White,
                                 zap.rotation, player.center, 1.0f, SpriteEffects.None, 0.5f);
            }

            spriteBatch.Draw(turret.sprite, turret.position + shadowOffset, null, Color.Black,
                        turret.rotation, turret.center, 1.0f, SpriteEffects.None, 0.5f);
                spriteBatch.Draw(turret.sprite, turret.position, null, Color.White,
                        turret.rotation, turret.center, 1.0f, SpriteEffects.None, 0);            

            foreach (GameObjects bullet in bullets)
            {
                if (bullet.alive == true)
                {
                    spriteBatch.Draw(bullet.sprite, bullet.position + shadowOffset, null, Color.Black,
                        bullet.rotation, bullet.center, 1.0f, SpriteEffects.None, 0.5f);
                    spriteBatch.Draw(bullet.sprite, bullet.position, null, new Color(192, 192, 192, 192),
                            bullet.rotation, bullet.center, 1.0f, SpriteEffects.None, 0);
                }
            }

            spriteBatch.End();

            spriteBatch.Begin();

            spriteBatch.DrawString(guiFont, dayString, new Vector2(750, 5), Color.Black);
            spriteBatch.DrawString(guiFont, timeString, new Vector2(750, 25), Color.Black);

            spriteBatch.DrawString(guiFont, score.ToString(), new Vector2(50, 25), Color.Black);

            spriteBatch.Draw(remote, new Vector2(700, 245), null, Color.White,
                             0f, Vector2.Zero, 0.5f, SpriteEffects.None, 0);

            //Draw the negative space for the health bar
            spriteBatch.Draw(healthBar, new Rectangle(ScreenManager.GraphicsDevice.Viewport.Width / 2 - healthBar.Width / 2,
                 30, healthBar.Width, 44), new Rectangle(0, 45, healthBar.Width, 44), Color.Gray);


            //Draw the current health level based on the current Health
            spriteBatch.Draw(healthBar, new Rectangle(ScreenManager.GraphicsDevice.Viewport.Width / 2 - healthBar.Width / 2,
                 30, (int)(healthBar.Width * ((double)player.health / 100)), 44),
                 new Rectangle(0, 45, healthBar.Width, 44), Color.Red);

            //Draw the box around the health bar
            spriteBatch.Draw(healthBar, new Rectangle(ScreenManager.GraphicsDevice.Viewport.Width/ 2 - healthBar.Width / 2,
                30, healthBar.Width, 44), new Rectangle(0, 0, healthBar.Width, 44), Color.White);

            spriteBatch.End();

            // If the game is transitioning on or off, fade it out to black.
            if (TransitionPosition > 0 || pauseAlpha > 0)
            {
                float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);

                ScreenManager.FadeBackBufferToBlack(alpha);
            }
        }

        private void Wander(Vector2 position, ref Vector2 wanderDirection,
           ref float orientation, float turnSpeed)
        {
            wanderDirection.X +=
                MathHelper.Lerp(-.25f, .25f, (float)random.NextDouble());
            wanderDirection.Y +=
                MathHelper.Lerp(-.25f, .25f, (float)random.NextDouble());

            if (wanderDirection != Vector2.Zero)
            {
                wanderDirection.Normalize();
            }

            orientation = TurnToFace(position, position + wanderDirection, orientation,
                .15f * turnSpeed);

            Vector2 screenCenter = Vector2.Zero;
            screenCenter.X = ScreenManager.GraphicsDevice.Viewport.Width / 2;
            screenCenter.Y = ScreenManager.GraphicsDevice.Viewport.Height / 2;

            float distanceFromScreenCenter = Vector2.Distance(screenCenter, position);
            float MaxDistanceFromScreenCenter =
                Math.Min(screenCenter.Y, screenCenter.X);

            float normalizedDistance =
                distanceFromScreenCenter / MaxDistanceFromScreenCenter;

            float turnToCenterSpeed = .3f * normalizedDistance * normalizedDistance *
                turnSpeed;

            orientation = TurnToFace(position, screenCenter, orientation,
                turnToCenterSpeed);
        }

        private static float TurnToFace(Vector2 position, Vector2 faceThis,
            float currentAngle, float turnSpeed)
        {
            float x = faceThis.X - position.X;
            float y = faceThis.Y - position.Y;
            float desiredAngle = (float)Math.Atan2(y, x);

            float difference = WrapAngle(desiredAngle - currentAngle);

            difference = MathHelper.Clamp(difference, -turnSpeed, turnSpeed);

            return WrapAngle(currentAngle + difference);
        }

        private static float WrapAngle(float radians)
        {
            while (radians < -MathHelper.Pi)
            {
                radians += MathHelper.TwoPi;
            }
            while (radians > MathHelper.Pi)
            {
                radians -= MathHelper.TwoPi;
            }
            return radians;
        }
        #endregion
    }
}
